In [1]:
import pandas as pd

Einlesen der Daten

In [2]:
# URLs der Daten
url_copper = "https://raw.githubusercontent.com/andreashrb/Python_for_ML_Project/main/data/dataset_copper.csv"
url_economic = "https://raw.githubusercontent.com/andreashrb/Python_for_ML_Project/main/data/copper_economic.csv"

Zeitreihendaten Kupferpreise

In [3]:
df_copper = pd.read_csv(url_copper, index_col=0, decimal=".", thousands=",", parse_dates=['date'])
In [4]:
df_copper.head()
Out[4]:
date lme_copper_cash lme_copper_three_month lme_copper_stock
0 2022-04-13 10290.5 10306.0 107000
1 2022-04-12 10201.0 10226.0 104350
2 2022-04-11 10235.5 10254.0 105600
3 2022-04-08 10390.0 10380.0 103775
4 2022-04-07 10292.0 10301.0 101275

Ökonomische Indikatoren für den Kupferpreis

In [5]:
df_economic = pd.read_csv(url_economic, index_col=0, encoding='utf-8')
In [6]:
df_economic.head()
Out[6]:
Jahr CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen CL_Produktionsmenge in 1000 Tonnen CN_Produktionsmenge in 1000 Tonnen MX_Produktionsmenge in 1000 Tonnen PE_Produktionsmenge in 1000 Tonnen ... US_Verbrauch in 1000 Tonnen AU_Reserven in Mio. Tonnen CL_Reserven in Mio. Tonnen CN_Reserven in Mio. Tonnen US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen
32 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 1630.0 440.0 1300.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
33 2013 7039.57 53245.52 21.42 3950.0 990.0 5780.0 1600.0 480.0 1380.0 ... 1828.0 87.0 190.0 30.0 39.0 20.0 38.0 70.0 30.0 20.0
34 2014 7645.88 55083.51 22.93 3960.0 970.0 5750.0 1760.0 515.0 1380.0 ... 1827.0 93.0 209.0 30.0 35.0 20.0 38.0 68.0 30.0 20.0
35 2015 8034.29 56729.68 23.06 3704.0 971.0 5760.0 1710.0 594.0 1700.0 ... 1829.0 88.0 210.0 30.0 33.0 20.0 46.0 82.0 30.0 20.0
36 2016 8063.45 57839.99 23.49 3634.0 948.0 5550.0 1900.0 752.0 2350.0 ... 1869.0 89.0 210.0 28.0 35.0 20.0 46.0 81.0 30.0 20.0

5 rows × 26 columns

Joinen der Datensätze

In [7]:
df_copper.dtypes
Out[7]:
date                      datetime64[ns]
lme_copper_cash                  float64
lme_copper_three_month           float64
lme_copper_stock                   int64
dtype: object
In [8]:
# Extrahieren des Jahres aus der Datetime-Spalte
df_copper['year'] = pd.DatetimeIndex(df_copper['date']).year
In [9]:
df_copper.head()
Out[9]:
date lme_copper_cash lme_copper_three_month lme_copper_stock year
0 2022-04-13 10290.5 10306.0 107000 2022
1 2022-04-12 10201.0 10226.0 104350 2022
2 2022-04-11 10235.5 10254.0 105600 2022
3 2022-04-08 10390.0 10380.0 103775 2022
4 2022-04-07 10292.0 10301.0 101275 2022
In [10]:
df_copper.dtypes
Out[10]:
date                      datetime64[ns]
lme_copper_cash                  float64
lme_copper_three_month           float64
lme_copper_stock                   int64
year                               int64
dtype: object
In [11]:
df_economic.dtypes
Out[11]:
Jahr                                    int64
CN_BIP pro Kopf in USD                float64
US_BIP pro Kopf in USD                float64
Global_Nachfrage in Mio. Tonnen       float64
EU_Produktionsmenge in 1000 Tonnen    float64
AU_Produktionsmenge in 1000 Tonnen    float64
CL_Produktionsmenge in 1000 Tonnen    float64
CN_Produktionsmenge in 1000 Tonnen    float64
MX_Produktionsmenge in 1000 Tonnen    float64
PE_Produktionsmenge in 1000 Tonnen    float64
RU_Produktionsmenge in 1000 Tonnen    float64
ZM_Produktionsmenge in 1000 Tonnen    float64
US_Produktionsmenge in 1000 Tonnen    float64
CN_Verbrauch in 1000 Tonnen           float64
EU_Verbrauch in 1000 Tonnen           float64
JP_Verbrauch in 1000 Tonnen           float64
US_Verbrauch in 1000 Tonnen           float64
AU_Reserven in Mio. Tonnen            float64
CL_Reserven in Mio. Tonnen            float64
CN_Reserven in Mio. Tonnen            float64
US_Reserven in Mio. Tonnen            float64
CG_Reserven in Mio. Tonnen            float64
MX_Reserven in Mio. Tonnen            float64
PE_Reserven in Mio. Tonnen            float64
RU_Reserven in Mio. Tonnen            float64
ZM_Reserven in Mio. Tonnen            float64
dtype: object
In [12]:
# Joinen der beiden Datensätze per Right-Join
df_copper_economic = pd.merge(left=df_copper, right=df_economic, how='right', left_on='year', right_on='Jahr')
df_copper_economic = df_copper_economic.drop('Jahr', axis = 1)
In [13]:
df_copper_economic.head()
Out[13]:
date lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen ... US_Verbrauch in 1000 Tonnen AU_Reserven in Mio. Tonnen CL_Reserven in Mio. Tonnen CN_Reserven in Mio. Tonnen US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen
0 2012-12-31 7915.0 7930.0 320050 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
1 2012-12-28 7870.0 7875.0 318050 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2 2012-12-27 7871.5 7900.0 318000 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
3 2012-12-24 7780.0 7801.5 317350 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
4 2012-12-21 7768.5 7792.0 312400 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0

5 rows × 30 columns

In [14]:
df_copper_economic.shape
Out[14]:
(2274, 30)

Der Datensatz hat 2274 Zeilen (Tagesbasierte Kupferschlusskurse + LME-Bestände). Dies entspricht einer Zeitreine von 2012 - 2020 (8 Jahre). Insgesamt verfügt der Datensatz über 30 Spalten.

Hinweis: Die Spalten "lme_copper_cash", "lme_copper_three_month", "lme_copper_stock" liegen tagesbasiert vor. Alle anderen Features sind lediglich Jahreswerte zum BIP, der globalen Kupfernachfrage, Produktionsmengen verschiedener Länder, Verbrauchsmengen verschiedener Länder, jahresbezogene Daten zur Nachfrage nach Kupfer und ebenso jährliche Daten zu Kupferreserven verschiedener Länder.

Ursprung der Daten:

  1. https://www.westmetall.com/en/markdaten.php?action=table&field=LME_Cu_cash
  2. https://de.statista.com/statistik/suche/?q=Kupfer&qKat=search&newSearch=true

Explorative Analyse der Zeitreihendaten

In [15]:
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import rcParams
import numpy as np
In [16]:
sns.set(style='whitegrid', palette='muted', font_scale=1.5)

rcParams['figure.figsize'] = 22, 10

Verteilungen

In [17]:
# Verteilung der Kupferpreise

plot_box1 = df_copper_economic['lme_copper_cash'].plot(kind='box', figsize = (13,8), 
                                            title = 'Verteilung des weltweiten Kupferpreises in US-Dollar pro Tonne') 

plot_box1.set_ylim(4000,10000)

plot_box1
Out[17]:
<AxesSubplot:title={'center':'Verteilung des weltweiten Kupferpreises in US-Dollar pro Tonne'}>
In [18]:
plot_hist1 = df_copper_economic['lme_copper_cash'].plot(kind='hist', figsize = (13,8), bins=50,
                                            title = 'Verteilung des weltweiten Kupferpreises in US-Dollar pro Tonne') 

plot_hist1
Out[18]:
<AxesSubplot:title={'center':'Verteilung des weltweiten Kupferpreises in US-Dollar pro Tonne'}, ylabel='Frequency'>

Erkenntnis:

Kupferpreise größer als ca. 8.800 USD sind Ausreißer am oberen Ende. Nach unten hin endet der Kupferpreis bei ca. 4.500 USD. Die Spanne der Kupferpreise reicht daher von ca. 4.500 USD bis hin zu ca. 8.800 USD, womit eine sehr hohe Preisspanne gegeben ist. Dies weist ggf. bereits auf starke Schwankungen der Preise - sowohl nach oben als auch nach unten - hin.

In [19]:
# Verteilung der Kupferreserven

plot_box2 = df_copper_economic['lme_copper_stock'].plot(kind='box', figsize = (13,8), 
                                            title = 'Verteilung der weltweiten Kupferreserven in Tonnen') 

plot_box2
Out[19]:
<AxesSubplot:title={'center':'Verteilung der weltweiten Kupferreserven in Tonnen'}>
In [20]:
plot_hist2 = df_copper_economic['lme_copper_stock'].plot(kind='hist', figsize = (13,8), bins=50,
                                            title = 'Verteilung der weltweiten Kupferreserven in Tonnen') 

plot_hist2
Out[20]:
<AxesSubplot:title={'center':'Verteilung der weltweiten Kupferreserven in Tonnen'}, ylabel='Frequency'>

Erkenntnis:

Ausreißer bei den Kupferreserven sind ab ca. 500.000 Tonnen zu erkennen. Die Spanne der Kupferreserven reicht von ca. 80.000 Tonnen bis hin zu knapp über 500.000 Tonnen. Es handelt sich um eine rechtsschiefe Verteilung.

Verlauf des täglichen Kupferpreises über die gesamte Zeitreihe

In [21]:
sns.lineplot(x='date', y="lme_copper_cash", data=df_copper_economic)
Out[21]:
<AxesSubplot:xlabel='date', ylabel='lme_copper_cash'>

Auf der x-Achse ist das Datum abgetragen. Auf der y-Achse ist der tägliche Kupferkurs in USD abgetragen. Die Zeitreihe geht vom 01.01.2012 bis zum 30.12.2020.

Zum generellen Trendverlauf: Von 2012 bis 2016 befand sich der Kupferpreis im freien Fall. Von über 8.000 USD ist der Kupferpreis auf letztlich ca. 4.500 USD gefallen. Seit 2016, mit einer kurzen Seitwärtsbewegung von ca. Mitte 2018 bis 2020 und einem Einbruch zu Beginn der Corona-Pandemie, steigt der Kupferpreis kurz nach dem coronabedingten Einbruch schließlich sehr stark bis auf ca. 8000 USD.

Der Kupferpreis unterliegt im Zeitverlauf starken Schwankungen. Das Rauschen und die Schwankungen in der Entwicklung des Kupferpreises werden im Folgenden noch genauer explorativ analysiert.

In [22]:
# Indexierung der Spalte "date"
df_copper_economic = df_copper_economic.set_index('date')
In [23]:
df_copper_economic.head()
Out[23]:
lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen CL_Produktionsmenge in 1000 Tonnen ... US_Verbrauch in 1000 Tonnen AU_Reserven in Mio. Tonnen CL_Reserven in Mio. Tonnen CN_Reserven in Mio. Tonnen US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen
date
2012-12-31 7915.0 7930.0 320050 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-12-28 7870.0 7875.0 318050 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-12-27 7871.5 7900.0 318000 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-12-24 7780.0 7801.5 317350 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-12-21 7768.5 7792.0 312400 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0

5 rows × 29 columns

Darstellung der monatlichen Entwicklung des Kupferpreises über die gesamte Zeitreihe

In [24]:
df_by_month = df_copper_economic.resample('M').mean()
df_by_month.head()
Out[24]:
lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen CL_Produktionsmenge in 1000 Tonnen ... US_Verbrauch in 1000 Tonnen AU_Reserven in Mio. Tonnen CL_Reserven in Mio. Tonnen CN_Reserven in Mio. Tonnen US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen
date
2012-01-31 8043.452381 8058.166667 353063.095238 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-02-29 8422.690476 8436.857143 311853.571429 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-03-31 8457.045455 8442.227273 268577.272727 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-04-30 8259.631579 8203.157895 260215.789474 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2012-05-31 7919.931818 7859.863636 225168.181818 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0

5 rows × 29 columns

In [25]:
sns.lineplot(x=df_by_month.index, y="lme_copper_cash", data=df_by_month);

Verlauf des täglichen Kupferpreises vs. der täglichen Kupferreserven

In [26]:
df_copper_economic = df_copper_economic.reset_index()
In [27]:
ax = df_copper_economic.plot(x="date", y="lme_copper_cash", legend=False)
ax2 = ax.twinx()
df_copper_economic.plot(x="date", y="lme_copper_stock", ax=ax2, legend=False, color="r")
ax.figure.legend()
ax.set_title('Entwicklung des Kupferpreises im Vergleich zu weltweiten Kupferreserven',fontdict={'fontsize': 25, 'fontweight': 'medium'})
plt.show()

Gegenstand der Betrachtung sind die tagesbasierten Kupferpreise und Lagerbestände (Reserven / LME Stocks) von Kupfer von 2012 bis Ende 2020.

Hypothese: Es ist davon auszugehen, dass die globalen Kupferreserven/Lagerbestände Einfluss auf die Preisbildung von Kupfer haben. Dies sollte im Rahmen dieser Visualisierung überprüft werden. Steigende Lagerbestände führen somit, eventuell auch zeitverzögert, zu sinkenden Kupferpreisen, während sinkende Reserven zu steigenden Kupferpreisen führen könnten.

Wie im abgebildeten Plot erkennbar, handelt es sich hier um keinen linearen Zusammenhang. Dennoch kann am Verlauf der Kupferreserven, im Vergleich zum Kupferpreis, festgemacht werden, dass die Kupferreserven in irgendeiner Form Einfluss auf den Kupferpreis haben.

Während sowohl die Kupferreserven und der Kupferpreis im Jahr 2012 relativ konstant blieben, stiegen die Kupferreserven (LME Stocks) im Jahr 2013 rasant an. Die Reserven (LME Stocks) erfuhren im Jahr 2013 mehr als eine Verdoppelung. In diesem Kontext setze der Kupferpreis den "Rückwärtsgang" ein. Nicht in der gleichen Geschwindigkeit, wie der Aufbau der Kupferreserven, dennoch ist anschließend ein kontinuierlicher und starker Abwärtstrend beim Kupferpreis zu erkennen. Der Kupferpreis fällt über die nächsten Jahre (bis ca. 2016) kontinuierlich von ca. 8000 USD auf fast 4.500 USD, während die vorhandenen und zu Beginn des Jahres 2013 aufgebauten Reserven kontinuierlich abgebaut werden.

Ein erneuter Aufbau der Reserven / Lagerbestände Mitte des Jahres 2015 sorgen für eine Preisstabilisierung von Kupfer (der Preisverfall ebbt ab). Während die Kupferreserven wieder verbraucht werden und auf das Niveau von Ende 2014 zurückkehren, verbleibt der Kupferpreis konstant bei unter 5.000 USD. Ein erneuter Aufbau der Reserven Mitte/Ende 2016, die letztlich im weiteren Zeitverlauf (trotz erheblicher Schwankungen) konstant bleiben sorgt Ende 2016 / Anfang 2017 für einen Preisanstieg, der bis Mitte 2018 anhält. Die Kupferreserven sind zu diesem Zeitpunkt auf einem hohen Niveau. Preiseinbrüche werden genutzt um die Reserven wieder aufzufüllen. So auch im Jahr 2020, zu Beginn der Corona-Pandemie, als der Kupferpreis einbricht. Diese Gelegenheit wird genutzt um die weltweiten Reserven wieder etwas aufzufüllen. Anschließend steigt der Preis von Kupfer atypisch stark. Der starke Preisanstieg in Folge des Auffüllens der Reserven und gewissen Corona-Sondereffekten wird durch Verbrauch vorhandener Reserven kompensiert. Dies treibt den Kupferpreis augenscheinlich weiter in die Höhe. Letztlich sind die Reserven zum Ende des Jahres 2020 auf einem sehr niedrigen Niveau und der Kupferpreis auf Rekordhoch.

Erkenntnis: Ein Zusammenhang kann festgestellt werden. Kupferreserven und Kupferpreis verhalten sich antizyklisch (gegenläufig), wobei eine ausschließliche und eindimensionale Abhängigkeit des Kupferpreises von den Kupferreserven ausgeschlossen werden kann. Ein zeitverzögerter Zusammenhang ist aber vorhanden.

Verlauf des monatlichen Kuperpreises vs. die monatlichen Kupferreserven

In [28]:
df_by_month = df_by_month.reset_index()
In [29]:
df_by_month.head()
Out[29]:
date lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen ... US_Verbrauch in 1000 Tonnen AU_Reserven in Mio. Tonnen CL_Reserven in Mio. Tonnen CN_Reserven in Mio. Tonnen US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen
0 2012-01-31 8043.452381 8058.166667 353063.095238 2012.0 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
1 2012-02-29 8422.690476 8436.857143 311853.571429 2012.0 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
2 2012-03-31 8457.045455 8442.227273 268577.272727 2012.0 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
3 2012-04-30 8259.631579 8203.157895 260215.789474 2012.0 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0
4 2012-05-31 7919.931818 7859.863636 225168.181818 2012.0 6282.71 51736.74 20.48 3882.0 958.0 ... 1832.0 86.0 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0

5 rows × 30 columns

In [30]:
ax = df_by_month.plot(x = 'date', y="lme_copper_cash", legend=False, color = 'b')
ax2 = ax.twinx()
df_by_month.plot(x = 'date', y="lme_copper_stock", ax=ax2, legend=False, color="r")
ax.figure.legend()
plt.show()

Gegenstand der Betrachtung sind die monatlichen Kupferpreise und Lagerbestände (Reserven / LME Stocks) von Kupfer von 2012 bis Ende 2020.

Hier bestätigt sich die Erkenntnis aus 3.3 noch einmal. Ein gegenläufiger Verlauf der Kupferreserven (LME-Lagerbestände) und dem Kupferpreis kann unterstellt werden, auch wenn es sich nicht um einen linearen Zusammenhang handelt.

Erkenntnis: Während in Monaten mit hohen Kupferreserven, etwas zeitverzögert, die Kupferpreise zu fallen beginnen, ist zu erkennen, dass im Anschluss eines stärkeren Verbrauchs der Reserven, ein Preisanstieg bzw. eine Unterbrechung des Abwärtstrends im Kupferpreis zu erkennen ist.

Ein konstantes Niveau der Kupferreserven lässt ebenso die Preisentwicklung für Kupfer stabilisieren. Die Corona-Pandemie hat Mitte des Jahres 2020 eine atypische Preisentwicklung in Bewegung gesetzt.

Visualisierung der durchschnittlichen Kupferpreise und Kupferreserven pro Quartal, Monat, Woche und Wochentag der gesamten Zeitreihe

Erstellen der benötigten Features

In [31]:
df_copper_economic['quarter'] = pd.DatetimeIndex(df_copper_economic['date']).quarter
df_copper_economic['month'] = pd.DatetimeIndex(df_copper_economic['date']).month
df_copper_economic['weekofyear'] = pd.DatetimeIndex(df_copper_economic['date']).weekofyear
df_copper_economic['weekday'] = pd.DatetimeIndex(df_copper_economic['date']).weekday
C:\Users\woelk\AppData\Local\Temp/ipykernel_13756/2847088666.py:3: FutureWarning: weekofyear and week have been deprecated, please use DatetimeIndex.isocalendar().week instead, which returns a Series.  To exactly reproduce the behavior of week and weekofyear and return an Index, you may call pd.Int64Index(idx.isocalendar().week)
  df_copper_economic['weekofyear'] = pd.DatetimeIndex(df_copper_economic['date']).weekofyear
In [32]:
df_copper_economic.head()
Out[32]:
date lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen ... US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen quarter month weekofyear weekday
0 2012-12-31 7915.0 7930.0 320050 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 39.0 20.0 38.0 76.0 30.0 20.0 4 12 1 0
1 2012-12-28 7870.0 7875.0 318050 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 39.0 20.0 38.0 76.0 30.0 20.0 4 12 52 4
2 2012-12-27 7871.5 7900.0 318000 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 39.0 20.0 38.0 76.0 30.0 20.0 4 12 52 3
3 2012-12-24 7780.0 7801.5 317350 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 39.0 20.0 38.0 76.0 30.0 20.0 4 12 52 0
4 2012-12-21 7768.5 7792.0 312400 2012 6282.71 51736.74 20.48 3882.0 958.0 ... 39.0 20.0 38.0 76.0 30.0 20.0 4 12 51 4

5 rows × 34 columns

In [33]:
df_copper_economic['weekday'].unique()
Out[33]:
array([0, 4, 3, 2, 1], dtype=int64)

Hinweis: Der Kupferpreis und die LME-Lagerbestände (Kupferreserven) liegen wochentags vor - Samstage und Sonntage sind nicht enthalten. Dies liegt am den Öffnungszeiten der LME-Börse in London.

0 = Montag

1 = Dienstag

2 = Mittwoch

3 = Donnerstag

4 = Freitag

Durchschnittlicher Kupferpreis pro Quartal, Monat, Woche und Wochentag gruppiert nach Jahren (von 2012 bis 2020)

In [34]:
# Gruppieren des Datensatzes mit Kupferpreis und Kupferreserven
df_aggregated_quarter = df_copper_economic[['year','quarter', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['year','quarter']).mean().reset_index()
df_aggregated_month = df_copper_economic[['year','month', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['year','month']).mean().reset_index()
df_aggregated_week = df_copper_economic[['year','weekofyear', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['year','weekofyear']).mean().reset_index()
df_aggregated_weekday = df_copper_economic[['year','weekday', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['year','weekday']).mean().reset_index()
In [35]:
df_aggregated_quarter.head()
Out[35]:
year quarter lme_copper_cash lme_copper_stock
0 2012 1 8310.062500 310499.218750
1 2012 2 7869.225000 242706.666667
2 2012 3 7705.750000 236718.359375
3 2012 4 7908.757812 250128.906250
4 2013 1 7931.475806 421071.370968
In [36]:
# Erstellen der Plots mit Subplots
fig,(ax1, ax2, ax3, ax4)= plt.subplots(nrows=4)
fig.set_size_inches(18, 28)

sns.pointplot(data=df_aggregated_quarter, x='quarter', y='lme_copper_cash', hue='year', ax=ax1)
sns.pointplot(data=df_aggregated_month, x='month', y='lme_copper_cash', hue='year', ax=ax2)
sns.pointplot(data=df_aggregated_week, x='weekofyear', y='lme_copper_cash', hue='year', ax=ax3)
sns.pointplot(data=df_aggregated_weekday, x='weekday', y='lme_copper_cash', hue='year', ax=ax4)
Out[36]:
<AxesSubplot:xlabel='weekday', ylabel='lme_copper_cash'>

Erkenntnisse:

Plot 1: In diesem Plot ist der durchschnittliche Kupferpreis aggregiert pro Quartal über die Jahre 2012 - 2020 abgebildet, um eventuelle saisonale Schwankungen innerhalb der Quartale eines Jahres zu identifizieren, die für eine spätere modellbasierte Prognose des Kupferpreises von Relevanz sein könnten.

Mit Ausnahme der Jahre 2017 und 2020 beginnt das 1. Quartal eines jeden Jahres mit einem, relativ zu den anderen Quartalen betrachteten, hohen Kupferpreis.Während die Quartale 2 und 3 entsprechend etwas schwächer (geringerer Kupferpreis) ausfallen, erholt sich der Kupferpreis i.d.R. im 4. Quartal wieder leicht.

Eine leichte quartalsweise Saisonalität und Tendenz des Kupferpreises kann also unterstellt werden. Dennoch bestimmen Ausnahmen die Regel. Von den betrachteten 8 Jahren der Zeitreihe folgen insbesondere die Jahre 2016, 2017, 2020 und nicht ganz konsequent diesem Muster.

Plot 2: In diesme Plot ist der durchschnittliche Kupferpreis aggregiert pro Monat über die Jahre 2012-2020 abgebildet, um eventuelle saisonale Schwankungen innerhalb der einzelnen Monate eines Jahres zu identifizieren, die für eine spätere modellbasierte Prgonose des Kupferpreises von Relevanz sein könnten.

Aus diesem Plot wird ebenfalls deutlich, dass der Kupferpreis insbesondere in den Sommermonaten (von Mai bis August) geringer ist, als in den ersten und letzten Monaten eines Jahres.

Plot 3: In diesem Plot ist der durchschnittliche Kupferpreis aggregiert pro Kalenderwoche (weekofyear) über die Jahre 2012-2020 abgebildet, um eventuelle saisonale Schwankungen innerhalb der einezlnen Monate eines Jahres zu identifizieren, die für eine spätere modellbasierte Prognose des Kupferpreises von Relevanz sein könnten.

Es lassen sich keine konkreten Kalenderwochen erkennen, die über alle Jahre der Zeitreihe (2012-2020) hinweg durchschnittlich höhere oder niedrigere Kupferpreise aufweisen. Dennoch zeichnen sich in diesem Plot erneut die bereits in Plot 1 und Plot 2 gewonnenen Erkenntnisse ab - wenn auch die Darstellung auf Ebene der Kalenderwochen deutlich weniger erkennbare Strukturen aufweist und eher die starke, unterjährige Volatilität des Kupferpreises andeutet.

Plot 4: In diesem Plot ist der durchschnittliche Kupferpreis aggregiert pro Wochentag über die Jahre 2012 - 2020 abgebildet.

Auf Ebene der Wochentage lässt sich kein Zusammenhang ableiten. Die durchschnittlichen Kuperpreise der jeweiligen Jahre sind an den jeweiligen Werktagen einer Woche sehr identisch ohne bestimmte Tendenzen nach oben oder unten an bestimmten Wochentagen.

Durchschnittlicher Kupferpreis pro Quartal, Monat, Woche und Wochentag (von 2012 bis 2020)

In [37]:
# Gruppieren des Datensatzes mit Kupferpreis und Kupferreserven
df_aggregated_quarter1 = df_copper_economic[['year','quarter', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['quarter']).mean().reset_index()
df_aggregated_month1 = df_copper_economic[['year','month', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['month']).mean().reset_index()
df_aggregated_week1 = df_copper_economic[['year','weekofyear', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['weekofyear']).mean().reset_index()
df_aggregated_weekday1 = df_copper_economic[['year','weekday', 'lme_copper_cash', 'lme_copper_stock']].groupby(by=['weekday']).mean().reset_index()
In [38]:
# Erstellen der Plots mit Subplots
fig,(ax1, ax2, ax3, ax4)= plt.subplots(nrows=4)
fig.set_size_inches(18, 28)

sns.pointplot(data=df_aggregated_quarter1, x='quarter', y='lme_copper_cash', ax=ax1)
sns.pointplot(data=df_aggregated_month1, x='month', y='lme_copper_cash', ax=ax2)
sns.pointplot(data=df_aggregated_week1, x='weekofyear', y='lme_copper_cash', ax=ax3)
sns.pointplot(data=df_aggregated_weekday1, x='weekday', y='lme_copper_cash', ax=ax4)
Out[38]:
<AxesSubplot:xlabel='weekday', ylabel='lme_copper_cash'>

Zusätzliche Erkenntnisse:

Bei der Betrachtung der durchschnittlichen Kuperpreise von 2012-2020 ohne Gruppierung auf einzelne Jahre, sondern unter Berücksichtigung (Berechnung des durchschnittlichen Kupferpreises) über alle in der Zeitreihe enthaltenen Jahre, bestätigt sich in den ersten beiden Plots die bereits im oberen Teil abgeleiteten Zusammenhänge.

Während das Quartal 1 und das Quartal 4 durchschnittlich höhere Kupferpreise aufweisen, ist der Kupferpreis in Q2 und Q3 tendenziell niedriger.

Die Monate Mai bis August weisen durchschnittlich, ohne die Differenzierung in einzelne Jahre, die geringsten Kupferpreise auf.

In der Kalenderwoche 53 brechen die Kupferpreise überdurchschnittlich stark ein, während die Eröffnung eines neuen Jahres in Kalenderwoche 1 i.d.R. deutlich höher ausfällt. Bis Kalenderwoche 9/10 steigt der durchschnittliche Kupferpreis deutlich, bis dann der Preisverfall mit Blick auf die Sommemonate und -wochen eintritt.

Auf Ebene der Wochentage zeigt sich, differenziert nach einzelnen Jahren, keine besondere Tendenz. Betrachtet man allerdings die gesamte Zeitreihe von 2012 - 2020 und die durchschnittlichen Kupferpreise zeichnet sich eine leichte Differenzierung der WOchentage und die damit verbundene Entwicklung der Kupferpreise ab.

Während der Kupferpreis von Montag bis MIttwoch tendenziell eine fallende Tendenz aufweist und durchschnittlich am Mittwoch seinen Tiefpunkt erreicht, steigt der Kupferpreis zum Wochenabschluss durchschnittlich nocheinmal an. Der Anstieg ist an dieser Stelle aber in den Kontext der Achsenskalierung zu setzen - ein besonders starker Anstieg des durchschnittlichen Kupferpreises liegt hier nicht vor.

Durchschnittliche Kupferreserven (LME-Stocks) pro Quartal, Monat, Woche und Wochentag gruppiert nach Jahren (von 2012 bis 2020)

In [39]:
fig,(ax1, ax2, ax3, ax4)= plt.subplots(nrows=4)
fig.set_size_inches(18, 28)

sns.pointplot(data=df_aggregated_quarter, x='quarter', y='lme_copper_stock', hue='year', ax=ax1)
sns.pointplot(data=df_aggregated_month, x='month', y='lme_copper_stock', hue='year', ax=ax2)
sns.pointplot(data=df_aggregated_week, x='weekofyear', y='lme_copper_stock', hue='year', ax=ax3)
sns.pointplot(data=df_aggregated_weekday, x='weekday', y='lme_copper_stock', hue='year', ax=ax4)
Out[39]:
<AxesSubplot:xlabel='weekday', ylabel='lme_copper_stock'>

Der eingangs in diesem Notebook angedeutete Zusammenhang von Kupferpreisentwicklung und der Entwicklung der Kupferreserven bestätigt sich in diesen Plots, die die durchschnittlichen Kupferreserven je Quartal, je Monat, je Kalenderwoche und je Kalendertag gruppiert nach den Jahren der Zeitreihe darstellen.

Während der Kupferpreis im ersten Quartal auf hohem Niveau startet und im letzten Quartal auf erhöhtem Niveau schließt, ist der Kupferpreis in den Sommerquartalen Q2 / Q3 tendenziell niedriger. Andersherum verhalten sich die Kupferreserven je Quartal und Jahr. Die Kupferreserven sind in den ersten Quartalen und Monaten eines jeden Jahres geringer als in den Sommermonaten.

Ein Zusammenhang der Reserven zur Preisentwicklung kann demnach nocheinmal bestätigt werden.

In der Gruppierung nach Jahren sind die durchschnittlichen Reserven je Wochentag sehr konstant, ohne besondere Auffälligkeiten und nennenswerten Zusammenhänge - ähnlich, wie bei der Preisentwicklung.

Durchschnittliche Kupferreserven (LME-Stocks) pro Quartal, Monat, Woche und Wochentag (von 2012 bis 2020)

In [40]:
# Erstellen der Plots mit Subplots
fig,(ax1, ax2, ax3, ax4)= plt.subplots(nrows=4)
fig.set_size_inches(18, 28)

sns.pointplot(data=df_aggregated_quarter1, x='quarter', y='lme_copper_stock', ax=ax1)
sns.pointplot(data=df_aggregated_month1, x='month', y='lme_copper_stock', ax=ax2)
sns.pointplot(data=df_aggregated_week1, x='weekofyear', y='lme_copper_stock', ax=ax3)
sns.pointplot(data=df_aggregated_weekday1, x='weekday', y='lme_copper_stock', ax=ax4)
Out[40]:
<AxesSubplot:xlabel='weekday', ylabel='lme_copper_stock'>

Die bisher gewonnenen Erkenntnisse bestätigen sich ebenfalls erneut bei Betrachtung der durchschnittlichen Kupferreserven pro Quartal, Monat, Woche und Wochentag über alle in der Zeitreihe enthaltenen Jahre (2012-2020).

Die Kupferreserven sind im ersten und letzten Quartal am niedrigsten. während die Kupferläger in den Quartalen 2 und 3 bei durchschnittlicher BEtrachtung gut gefüllt sind. Analog bzw. invers verhält sich die Preisentwicklung.

Während die Kupferreserven in KW53 ihren Tiefpunkt erreichen und durchschnittlich von KW 1 - KW10 steigen und sich in den Sommermonaten und -wochen dann auf hohem Niveau befinden, fällt nach dem Aufbau der Lagerbestände der Kupferpreis, wie wir oben bereits erläutert haben. Augenscheinlich werden über den Jahreswechsel hinweg die Reserven wieder aufgefüllt, was zu Jahresbeginn zu deutlich höheren Eröffnungspreisen, verglichen mit den Schlusspreisen in der KW 53, führt.

Auf Basis der Wochentage lässt sich eine leichte Tendenz dahingehend erkennen, dass der durchschnittliche verfügbare Bestand LME-Stock) an Montagen geringer ist, als an anderen Tagen der Woche. Mit Blick auf die Achsenskalierung des Plots ist die Differenz bei Betrachtung der Wochentage allerdings nicht besonders stark.

Vergleich der durchschnittlichen Kupferpreise und Kupferreserven pro Jahr mit der jährlichen Nachfrage, Produktionsmenge und Verbrauchsmenge

In [41]:
# Anzeige der Spalten unseres DataFrames
df_copper_economic.columns
Out[41]:
Index(['date', 'lme_copper_cash', 'lme_copper_three_month', 'lme_copper_stock',
       'year', 'CN_BIP pro Kopf in USD', 'US_BIP pro Kopf in USD',
       'Global_Nachfrage in Mio. Tonnen', 'EU_Produktionsmenge in 1000 Tonnen',
       'AU_Produktionsmenge in 1000 Tonnen',
       'CL_Produktionsmenge in 1000 Tonnen',
       'CN_Produktionsmenge in 1000 Tonnen',
       'MX_Produktionsmenge in 1000 Tonnen',
       'PE_Produktionsmenge in 1000 Tonnen',
       'RU_Produktionsmenge in 1000 Tonnen',
       'ZM_Produktionsmenge in 1000 Tonnen',
       'US_Produktionsmenge in 1000 Tonnen', 'CN_Verbrauch in 1000 Tonnen',
       'EU_Verbrauch in 1000 Tonnen', 'JP_Verbrauch in 1000 Tonnen',
       'US_Verbrauch in 1000 Tonnen', 'AU_Reserven in Mio. Tonnen',
       'CL_Reserven in Mio. Tonnen', 'CN_Reserven in Mio. Tonnen',
       'US_Reserven in Mio. Tonnen', 'CG_Reserven in Mio. Tonnen',
       'MX_Reserven in Mio. Tonnen', 'PE_Reserven in Mio. Tonnen',
       'RU_Reserven in Mio. Tonnen', 'ZM_Reserven in Mio. Tonnen', 'quarter',
       'month', 'weekofyear', 'weekday'],
      dtype='object')
In [42]:
# Gruppieren des Datensatzes mit Kupferpreis und Kupferreserven und diversen Indikatoren nach "Jahr"
df_aggregated_year = df_copper_economic[['year', 'lme_copper_cash', 'lme_copper_three_month', 'lme_copper_stock',
       'CN_BIP pro Kopf in USD', 'US_BIP pro Kopf in USD',
       'Global_Nachfrage in Mio. Tonnen', 'EU_Produktionsmenge in 1000 Tonnen',
       'AU_Produktionsmenge in 1000 Tonnen',
       'CL_Produktionsmenge in 1000 Tonnen',
       'CN_Produktionsmenge in 1000 Tonnen',
       'MX_Produktionsmenge in 1000 Tonnen',
       'PE_Produktionsmenge in 1000 Tonnen',
       'RU_Produktionsmenge in 1000 Tonnen',
       'ZM_Produktionsmenge in 1000 Tonnen',
       'US_Produktionsmenge in 1000 Tonnen', 'CN_Verbrauch in 1000 Tonnen',
       'EU_Verbrauch in 1000 Tonnen', 'JP_Verbrauch in 1000 Tonnen',
       'US_Verbrauch in 1000 Tonnen', 'AU_Reserven in Mio. Tonnen',
       'CL_Reserven in Mio. Tonnen', 'CN_Reserven in Mio. Tonnen',
       'US_Reserven in Mio. Tonnen', 'CG_Reserven in Mio. Tonnen',
       'MX_Reserven in Mio. Tonnen', 'PE_Reserven in Mio. Tonnen',
       'RU_Reserven in Mio. Tonnen', 'ZM_Reserven in Mio. Tonnen']].groupby(by=['year']).mean().reset_index()

Durchschnittliche Produktionsmengen nach Ländern von 2012-2020

In [43]:
ax = df_aggregated_year.plot(x = 'year', y='EU_Produktionsmenge in 1000 Tonnen', legend=False, color = 'b')
ax2 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="AU_Produktionsmenge in 1000 Tonnen", ax=ax2, legend=False, color = 'g')
ax3 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="CL_Produktionsmenge in 1000 Tonnen", ax=ax3, legend=False, color = 'r')
ax4 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="CN_Produktionsmenge in 1000 Tonnen", ax=ax4, legend=False, color = 'c')
ax5 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="MX_Produktionsmenge in 1000 Tonnen", ax=ax5, legend=False, color = 'm')
ax6 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="PE_Produktionsmenge in 1000 Tonnen", ax=ax6, legend=False, color = 'y')
ax7 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="RU_Produktionsmenge in 1000 Tonnen", ax=ax7, legend=False, color = 'k')
ax8 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="ZM_Produktionsmenge in 1000 Tonnen", ax=ax8, legend=False, color = 'w')
ax9 = ax.twinx()
df_aggregated_year.plot(x = 'year', y="US_Produktionsmenge in 1000 Tonnen", ax=ax9, legend=False, color = '0.75')
ax.figure.legend()
plt.show()

Erkenntnis: Eine Tendenz, dass die Produktionsmengen der letzten 8 Jahre sich sehr analog zum Kupferpreis verhalten, lässt sich ableiten. Die Betrachtung der kumulierten Produktionsmenge (Summe aller Produktionsmengen aller Länder in den letzten Jahren) würde hier eventuell noch einmal ein klareres Bild zur "globalen Produktionsmenge" und dessen Verlauf geben.

Üblicherweise wäre davon auszugehen, dass hohe Produktionsmengen zu geringeren Preisen und umgekehrt führen. Auf den ersten Blick lässt sich das nicht bestätigen, allerdings wäre hierfür auch der Kupferverbrauch gegenüberzustellen. Denn auch dieser kann widerum Einfluss auf die Preisbildung haben - auch wenn die Produktionsmengen sehr gering sind, gleichzeitig der Verbrauch aber ebenfalls gering ist, kann dies zu einer Preisentwicklung nach unten oder, im umgekehrten Fall, nach oben führen.

Durchschnittliche Verbrauchsmengen nach Ländern von 2012-2020

In [44]:
ax = df_aggregated_year.plot(x = 'year', y='CN_Verbrauch in 1000 Tonnen', legend=False, color = 'b')
ax2 = ax.twinx()
df_aggregated_year.plot(x = 'year', y='EU_Verbrauch in 1000 Tonnen', ax=ax2, legend=False, color = 'g')
ax3 = ax.twinx()
df_aggregated_year.plot(x = 'year', y='JP_Verbrauch in 1000 Tonnen', ax=ax3, legend=False, color = 'r')
ax4 = ax.twinx()
df_aggregated_year.plot(x = 'year', y='US_Verbrauch in 1000 Tonnen', ax=ax4, legend=False, color = 'c')

ax.figure.legend()
plt.show()

Durchschnittliche (kum.) globale Produktionsmengen und Verbrauchsmengen im Vergleich zu Kupferpreis und Kupferreserven von 2012-2020

In [45]:
# Liste aller Spalten zu den Produktionsmengen einzelner Länder
copper_produktionsmengen = ['EU_Produktionsmenge in 1000 Tonnen',
       'AU_Produktionsmenge in 1000 Tonnen',
       'CL_Produktionsmenge in 1000 Tonnen',
       'CN_Produktionsmenge in 1000 Tonnen',
       'MX_Produktionsmenge in 1000 Tonnen',
       'PE_Produktionsmenge in 1000 Tonnen',
       'RU_Produktionsmenge in 1000 Tonnen',
       'ZM_Produktionsmenge in 1000 Tonnen',
       'US_Produktionsmenge in 1000 Tonnen']
In [46]:
# Additiion der Produktionsmengen aller Länder und Zusammenführung in Spalten "Global_Produktionsmengen"
df_copper_economic['Global_Produktionsmenge in 1000 Tonnen'] = df_copper_economic[copper_produktionsmengen[0]] +df_copper_economic[copper_produktionsmengen[1]] +df_copper_economic[copper_produktionsmengen[2]] +df_copper_economic[copper_produktionsmengen[3]] +df_copper_economic[copper_produktionsmengen[4]] +df_copper_economic[copper_produktionsmengen[5]] +df_copper_economic[copper_produktionsmengen[6]] +df_copper_economic[copper_produktionsmengen[7]] +df_copper_economic[copper_produktionsmengen[8]]
In [47]:
# Liste aller Spalten zu den Verbrauchsmengen einzelner Länder
copper_verbrauch = ['CN_Verbrauch in 1000 Tonnen',
       'EU_Verbrauch in 1000 Tonnen', 'JP_Verbrauch in 1000 Tonnen',
       'US_Verbrauch in 1000 Tonnen', 'AU_Reserven in Mio. Tonnen']
In [48]:
# Additiion der Verbrauchsmengen unterschiedlicher Länder und Zusammenführung in Spalten "Global_Verbrauch"
df_copper_economic['Global_Verbrauch in 1000 Tonnen'] = df_copper_economic[copper_verbrauch[0]] + df_copper_economic[copper_verbrauch[1]] + df_copper_economic[copper_verbrauch[2]] + df_copper_economic[copper_verbrauch[3]] + df_copper_economic[copper_verbrauch[4]]
In [49]:
# Gruppieren des Datensatzes mit Kupferpreis und Kupferreserven und diversen Indikatoren nach "Jahr"
df_aggregated_year_produktion = df_copper_economic[['year', 'lme_copper_cash', 'lme_copper_stock', 'Global_Produktionsmenge in 1000 Tonnen', 'Global_Verbrauch in 1000 Tonnen']].groupby(by=['year']).mean().reset_index()
In [50]:
# Erstellen der Plots mit Subplots
fig,(ax1, ax2, ax3, ax4)= plt.subplots(nrows=4)
fig.set_size_inches(18, 28)

sns.pointplot(data=df_aggregated_year_produktion, x='year', y='lme_copper_cash', ax=ax1)
sns.pointplot(data=df_aggregated_year_produktion, x='year', y='lme_copper_stock', ax=ax2)
sns.pointplot(data=df_aggregated_year_produktion, x='year', y='Global_Produktionsmenge in 1000 Tonnen', ax=ax3)
sns.pointplot(data=df_aggregated_year_produktion, x='year', y='Global_Verbrauch in 1000 Tonnen', ax=ax4)
Out[50]:
<AxesSubplot:xlabel='year', ylabel='Global_Verbrauch in 1000 Tonnen'>

Erkenntnis: Der durchschnittliche Kupferpreis pro Jahr fällt, wie bereits weiter oben in diesem Notebook dargestellt, von 2012-2016 kontinuierlich auf ein Niveau von etwas unter 5.000 USD. Anschließend stabilisiert sich der durchschnittliche Kupferpreis im Jahr 2017 und bleibt seitdem, natürlich mit einigen Schwankungen, weistgehend konstant (gleichbleibendes Niveau).

Diese Entwicklung zeichnet sich analog, aber im umgekehrten Sinne, bei der Produktionsmenge ab.

Während die jährliche Produktionsmenge im Jahr 2012 sehr gering war und bis 2016 kontinuierlich steigt, stabilisiert sich diese ab 2017 mit eher geringeren Schwankungen in der Jahresproduktionsmenge bis zum Jahr 2020. Eine steigende Produktionsmenge führt also mit einer gewissen zeitlichen Verzögerung zu sinkenden Kupferpreisen, wie man dies volkswirtschaftlich (Angebot und Nachfrage) auch erwarten würde. Eine stagnierende Produktionsmenge hat eine stagnierende Wirklung auf den Kupferpreis.

Mit Blick auf den jährlichen Kupferverbrauch der Länder, die zu den größten Verbrauchern/Nutzern von Kupfer als Rohstoff gehören, zeigt sich, dass die Entwicklung der Verbrauchsmengen in 1000 Tonnen sehr ähnlich zur Produktionsmenge in 1000 Tonnen verläuft. Im Jahr 2016 war das GAP (Differenz) zw. Verbrauchs- und Produktionsmenge am Höchsten. In den Jahren 2012 - 2016 gibt es ein erhebliches GAP zw. dem Kupferverbrauch und der Kupferproduktionsmenge, was den fallenden Preistrend in dieser Zeit erklärbar macht.

Ab dem Jahr 2017 liegt die Produktionsmenge immer noch leicht über der Verbrauchsmenge in 1000 Tonnen allerdings wird diese Differenz im Laufe der Jahre 2018 - 2020 immer geringer, was die Stabilisierung des Preises aus dieser Perspektive unterstreichen würde.

Ebenfalls macht die Entwicklung von Verbräuchen und Produktionsmengen auch die Entwicklung der Lagerbestände erklärbarer. Der Kupferpreis steigt im Jahr 2020 dramatisch an, was sich auch leicht im Durchschnittspreis für Kupfer für das Jahr 2020 niederschlägt. Im Jahr 2020 wurde die durchschnittliche Produktionsmenge im Vergleich zum Vorjahr deutlich reduziert, während die Verbräuche nur leicht zurückgingen - die durchschnittlichen Reserven von Kupfer sind für das Jahr 2020 auch noch einmal gefallen. Dies führt zu einem, durchschnittlich betrachtet, leichten Preisanstieg bei Kupfer im Vergleich zu den Vorjahren.

Entwicklung des BIP in China und USA im Vergleich zu jahresdurchschnittlichen Kupferpreisen und Kupferreserven

In [51]:
# Gruppieren des Datensatzes mit Kupferpreis und Kupferreserven und BIP (China, USA) nach "Jahr"
df_aggregated_year_bip = df_copper_economic[['year', 'lme_copper_cash', 'lme_copper_stock', 'US_BIP pro Kopf in USD' , 'CN_BIP pro Kopf in USD', 'Global_Produktionsmenge in 1000 Tonnen', 'Global_Verbrauch in 1000 Tonnen']].groupby(by=['year']).mean().reset_index()
In [52]:
# Erstellen der Plots mit Subplots
fig,(ax1, ax2, ax3, ax4)= plt.subplots(nrows=4)
fig.set_size_inches(18, 28)

sns.pointplot(data=df_aggregated_year_bip, x='year', y='lme_copper_cash', ax=ax1)
sns.pointplot(data=df_aggregated_year_bip, x='year', y='lme_copper_stock', ax=ax2)
sns.pointplot(data=df_aggregated_year_bip, x='year', y='US_BIP pro Kopf in USD', ax=ax3)
sns.pointplot(data=df_aggregated_year_bip, x='year', y='CN_BIP pro Kopf in USD', ax=ax4)
Out[52]:
<AxesSubplot:xlabel='year', ylabel='CN_BIP pro Kopf in USD'>

Erkenntnis:

Aus dem jährlichen Verlauf des BIP der größten Volkswirtschaften der Welt, China und USA, und dem Verlauf des Kupferpreises lässt sich kein direkter Zusammenhang ableiten. Das BIP der beiden größten Volkswirtschaften der Welt, die sich vor allem durch starke Technologiesektoren auszeichnen und daher ebenso signifikante Verbraucher/Nutzer von Kupfer sind, steigt seit 2012 kontinuierlich, nahezu linear, an. Die USA verzeichnete im Jahr 2020, sehr stark durch die Corona-Pandemie beeeinflusst, einen leichten Rückgang des BIP pro Kopf, während das BIP pro Kopf in China weiter ansteigt.

Insgesamt liegt das BIP pro Kopf in China weit unter dem BIP pro Kopf in den USA. Die Verläufe/Entwicklung des BIP ist in beiden Ländern (Volkswirtschaften) aber grundsätzlich sehr vergleichbar.

Die relative Entwicklung des BIP pro Kopf von 2012- 2020 war in China deutlich größer, als in den USA.

Ein Zusammenhang zw. BIP pro Kopf und der jährlich durchschnittlichen Produktions- und Verbrauchsmengen von Kupfer lässt sich allerdings unterstellen, wie folgeder Plot noch einmal deutlich zeigen soll:

In [53]:
ax = df_aggregated_year_bip.plot(x = 'year', y='US_BIP pro Kopf in USD', legend=False, color = 'b')
ax2 = ax.twinx()
df_aggregated_year_bip.plot(x = 'year', y='CN_BIP pro Kopf in USD', ax=ax2, legend=False, color = 'c')
ax3 = ax.twinx()
df_aggregated_year_bip.plot(x = 'year', y='Global_Verbrauch in 1000 Tonnen', ax=ax3, legend=False, color = '0.5')
ax4 = ax.twinx()
df_aggregated_year_bip.plot(x = 'year', y='Global_Produktionsmenge in 1000 Tonnen', ax=ax4, legend=False, color = '0.2')

ax.figure.legend()
plt.show()
  • Grau: Verbrauchs- und Produktionsmengen
  • Blau: BIP der USA / China

Erkenntnis:

Die Entwicklung (Wachstum) des jährlichen BIP und der jährlichen Verbrauchs- und Produktionsmengen verlaufen sehr identisch, was einen Zusammenhang unterstellen lässt.

Das Wachstum des BIP in den größten, vom Technologiesektor getriebenen, Volkswirtschaften verursacht höhere Verbräuche von Kupfer. Dies macht höhere Produktionsmengen notwendig, um die Bedarfe der Märkte zu decken.

Das Zusammenspiel von Produktionsmenge und Verbrauch von Kupfer haben EInfluss auf die Bildung von Kupferreserven. Die Kupferreserven wiederum haben, wie wir weiter oben festgestellt haben, Einfluss auf die Preisbildung am Kupfermarkt, denn Kupferreserven und Kupferpreise scheinen sich ein Stück weit entgegengesetzt, wie man das volkswirtschaftlich auch erwarten würde, zu entwickeln.

Decomposition - Saisonalität, Trend und Rauschen

In [54]:
import statsmodels.api as sm
In [55]:
# Indexierung der Spalte "date"
df_copper_economic = df_copper_economic.sort_values('date', ascending=True)
df_copper_economic_decom = df_copper_economic.set_index('date')
df_copper_economic_decom.head()
Out[55]:
lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen CL_Produktionsmenge in 1000 Tonnen ... MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen quarter month weekofyear weekday Global_Produktionsmenge in 1000 Tonnen Global_Verbrauch in 1000 Tonnen
date
2012-01-03 7661.0 7680.0 371575 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1 1 1 1 16383.0 14429.0
2012-01-04 7652.0 7665.5 369150 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1 1 1 2 16383.0 14429.0
2012-01-05 7471.0 7485.5 368400 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1 1 1 3 16383.0 14429.0
2012-01-06 7515.0 7540.0 368125 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1 1 1 4 16383.0 14429.0
2012-01-09 7503.0 7508.0 366900 2012 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1 1 2 0 16383.0 14429.0

5 rows × 35 columns

In [56]:
# Plotten der saisonalen Muster der Zeitreihe (Kupferpreis)
decomposition = sm.tsa.seasonal_decompose(df_copper_economic_decom["lme_copper_cash"], period = 253)
decomposition.seasonal.plot()
plt.title('Saisonalität des Kupferpreises')
plt.show()
In [57]:
# Plotten der saisonalen Muster der Zeitreihe (Kupferreserven - LME-Stocks)


decomposition2 = sm.tsa.seasonal_decompose(df_copper_economic_decom["lme_copper_stock"], period= 253)
decomposition2.seasonal.plot()
plt.title('Saisonalität der Kupferbestände')
plt.show()

Erkenntnis: Betrachtet man die Saisonalität bzw. saisonalen Muster der beiden Zeitreihen (Kupferpreis und Kupferreserven) lässt sich unsere o.g. Erkenntnis, dass Kupferpreis und Kupferreserven gegenläufige Effekte udn damit Abhängigkeiten aufweisen, bestätigen. Die saisonalen Muster der Zeitreihen verlaufen ziemlich stark entgegengesetzt zueinander.

In [58]:
# Plotten des Trendverlaufs des Kupferpreises in der gegebenen Zeitreihe von 2012-2020

decomposition.trend.plot()
plt.ylabel('copper_price')
plt.title('Trendverlauf des Kupferpreises')
plt.show()
In [59]:
decomposition2.trend.plot()
plt.ylabel('copper_stock')
plt.title('Trendverlauf der Kupferbestände')
plt.show()

Erkenntnis: Der grundsätzliche Trend ist, sowohl beim Kupferpreis, als auch bei den Kupferreserven, fallend. Darüber hinaus lassen sich mit den Trendplots, bereits identifizierte Abhängigkeiten zw. Kupferreserven und Kupferpreis noch einmal bestätigen.

Ein hoher Kupferbestand bewirkt zeitverzögert einen Preisverfall beim Kupferpreis, während geringe Kupferbestände einen Preisanstieg bewirken, der durch das erhöhte Nachfrageverhalten zum Aufbau neuer Bestände hervorgerufen wird. Seit 2017 ist ein leichter Aufwärtstrend bei der Kupferpreisentwicklung festzustellen, während die Bestände seit 2017 durchschnittlich eher gesunken sind.

In [60]:
# Plotten des Rauschens in der Zeitreihe des Kupferpreises
decomposition.resid.plot()
plt.title('Rauschen des Kupferpreises')
plt.ylabel('Copper price')
plt.show()
In [61]:
# Plotten des Rauschens in der Zeitreihe der Kupferbestände/Kupferreserven

decomposition2.resid.plot()
plt.title('Rauschen der Kupferbestände')
plt.ylabel('copper stock')
plt.show()

Erkenntnis: In beiden Zeitreihen liegt ein nicht unerhebliches Rauschen, welches nicht durch saisonale Effekte oder die Trendkomponente in der Zeitreihe erklärt werden kann. Das Rauschen in der Zeitreihe sind entsprechende Ausreißerwerte, die weder durch die saisonale Komponente, noch die Trendkomponente, erklärt werden können.

Autokorrelation und partielle Autokorrelation

In [62]:
from statsmodels.graphics import tsaplots

Autokorrelation

In [63]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferpreisentwicklung
fig = tsaplots.plot_acf(df_copper_economic_decom["lme_copper_cash"], lags=500)
plt.title('Autokorrelation (ACF) des Kupferpreises')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper price)")
plt.show()
In [64]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferbestandsentwicklung
fig = tsaplots.plot_acf(df_copper_economic_decom["lme_copper_stock"], lags=500)
plt.title('Autokorrelation (ACF) der Kupferreserven')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper stock)")
plt.show()

Erkenntnis: Autokorrelation ist eine Methode der Zeitreihenanalyse. Sie bildet den Korrelationskoeffizienten, anders als bei klassischen Korrelationsanalysen, nicht zwischen verschiedenen Feautures eines Datensatzes ab, sondern bildet die Korrelation (Zusammenhänge) der Zielvariable und deren statistische Signifikanz gegenüber früheren Zeitpunkten ab.

An den beiden Autokorrelationsplots ist erkennbar, dass der stärkste zeitliche Zusammenhang, sowohl beim Kupferpreis, als auch bei den Kupferreserven, bei relativ kleinen "Lags" zu vorliegt. Starke Saisonalität in der Zeitreihe würde einen sprunghaften Anstieg der Korrelation an einer bestimmten Stelle des "Lag" auf der X-Achse bedeuten.

Weiter oben haben wir saisonale Stukturen innerhalb der Zeitreihen zum Kupferpreis und zu den Kupferreserven festgestellt. Diese scheinen, wie diese Plots noch einmal eindringlich zeigen, nicht besonders stark/signifikant zu sein.

Im Autokorrelationsplot des Kupferpreises sind Wellen bei einem Lag von ungefähr 250 zu erkennen, allerdings bewegen sich diese leicht erhöhten Korrelationen mit einem Lag von 250 im statistisch nicht signifikanten Bereich (blau hinterlefte Fläche).

Gleiches gilt für die Autokorrelation der Kupferreserven. Die stärkste Korrelation liegt bei relativ kleinen Lags vor. Ab einem Lag von 100 verliert die Korrelation / der Zusammenhang seine statistische Signifikanz. Auch hier sind wellenförmige Bewegungen der Autokorrelation zu erkennen, allerdings ebenfalls im Bereich des hellblau hinterlegten Bereichs (ergo: statistisch nicht signifikant).

Partielle Autokorrelation

In [65]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferpreisentwicklung
fig = tsaplots.plot_pacf(df_copper_economic_decom["lme_copper_cash"], lags=50)
plt.title('Partielle Autokorrelation des Kupferpreises')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper price)")
plt.show()
C:\Users\woelk\anaconda3\envs\condatascience2\lib\site-packages\statsmodels\graphics\tsaplots.py:348: FutureWarning: The default method 'yw' can produce PACF values outside of the [-1,1] interval. After 0.13, the default will change tounadjusted Yule-Walker ('ywm'). You can use this method now by setting method='ywm'.
  warnings.warn(
In [66]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferpreisentwicklung
fig = tsaplots.plot_pacf(df_copper_economic_decom["lme_copper_stock"], lags=50)
plt.title('Partielle Autokorrelation der Kupferreserven')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper stock)")
plt.show()
C:\Users\woelk\anaconda3\envs\condatascience2\lib\site-packages\statsmodels\graphics\tsaplots.py:348: FutureWarning: The default method 'yw' can produce PACF values outside of the [-1,1] interval. After 0.13, the default will change tounadjusted Yule-Walker ('ywm'). You can use this method now by setting method='ywm'.
  warnings.warn(

Erkenntnisse: Die partielle Autokorrelation wird ähnlich dargestellt, wie die Autokorrelation. Der wesentliche Unterschied der partiellen Autokorrelation zur Autokorrelation besteht darin, dass die partielle Autokorrelationversucht den Effekt der dazwischenliegenden Verzögerungen (=Lags) zu berücksichtigen. Demnach wird hier sozusagen der Mehrwert jeder weiteren Verzögerung in Form eines Korrelationskoeffizienten ausgedrückt.

Die größte Erklärungswirkung des Zusammenhangs geht von den ersten beiden Verzögerungen (=Lags) aus, anschließend wird jede weitere Verzögerung und ihr Beitrag zur Erklärung des Zusammenahngs statistisch nicht mehr signifikant oder sogar (bei den Kupferreserven) negativ. Ein negativer Wert im Rahmen der partiellen Autokorrelation bedeutet, dass durch vorangegangene Verzögerungen (=Lags) erklärte Zusammenhänge wieder vernichtet werden.

Zwischenfazit der explorativen Zeitreihenanalyse

Im Rahmen der explorativen Analyse der Zeitreihendaten zur tagesbasierten Kupferpreisentwicklung, der Entwicklung der täglichen Kupferreserven (LME-Stocks), angereichert um jahresbezogene Indikatoren zum BIP der beiden größten Volkswirtschaften der Welt (China und USA) und den jährlichen Verbrauchs- und Produktionsmengen wichtiger Volkswirtschaften im Kupfermarkt konnten einige wichtige, ggf. für die modellbasierte Prognose des Kupferpreises relevante, Erkenntnisse gewonnen und Zusammenhänge aufgezeigt werden.

Zusammenfassung:

Der Kupferpreis weist gewisse Saisonalitäten in Bezug auf Quartale, Monate, Wochen und Wochentage auf, die im Rahmen dieses Notebooks ausführlich beschrieben und aufgezeigt wurden. Insbesondere auf Ebene der Quartale und Monate der jeweiligen Jahre der hier vorliegenden Zeitreihe konnte anhand des durchschnittlichen Kupferpreises aufgezeigt werden, inwieweit saisonale Effekte im Kupferpreis und dessen Entwicklung enthalten sind bzw. sein könnten. Entsprechende zeitbasierte Features können bei der Prognose des Kupferpreises und dessen Entwicklung demnach eventuell dienlich sein.

Die Quartale Q2 und Q3 der betrachteten Jahre weisen grundsätzlich geringere Kupferpreise auf, als es in den Quartalen 1 und 4 der jeweiligen Jahre der Fall ist. Noch präziser wird diese Entwicklung von der monatlichen Darstellung der durchschnittlichen Kupferpreise über die Jahre 2012-2020 widergespiegelt.

Im Rahmen der Autokorrelationsanalyse und Analyse zur partiellen Autokorrelation wurde allerdings deutlich, dass diese saisonalen Muster in vielen Teilen nicht besonders stark bzw. nicht statistisch siginifikant zu sein scheinen. Die größte Erklärungswirkung für einen Zusammenhang innerhalb der Zeitreihe geht von verhältnismäßig kleinen Verzögerungen der Zeitreihe (Lags) aus.

Ebenso ist eine Erkenntnis aus den Decomposition-Plots (hinsichtlich Trend, Saisonalität und Rauschen), dass das Rauschen in den Zeitreihen zum Kupferpreis und zu den Kupferreserven die saisonale- und Trendkomponente an vielen Stellen dominiert.

Neben diesen zeitbasierten Informationen im Hinblick auf das Verschieben/Verzögern der Zeitreihe, der saisonalen, als auch der Trendkomponente, ließen sich Abhängigkeiten der Kupferpreisentwicklung zu den jährlichen Produktions- und Verbrauchsmengen ableiten. Ebenso ließ sich der Einfluss der durchschnittlich verfügbaren Kupferreserven auf die Kupferpreisentwicklung feststellen. Auch die Entwicklung des BIP der größten Volkswirtschaften der Welt, die stark durch ihre Technologiesektoren getrieben werden, weist gewisse Parallelen und Zusammenhänge zu den jährlichen Produktions- und Verbrauchsmengen auf. Die Differenz aus Produktions- und Verbrauchsmengen eines jeden Jahres der Zeitreihe (2012-2020) lässt möglicherweise Rückschlüsse auf den Verlauf der Kupferreserven zu.

Allerdings ist an dieser Stelle anzumerken, dass die jahresbezogenen Features nicht dabei helfen werden, die unterjährig auftretenden Schwankungen im Kupferpreis in irgendeiner Weise besser prognostizieren zu können. Aufgrund der hohen Volatilität der tagesbezogenen Kupferpreis- und Kupferbestandsdaten werden die jahresbezogenen volkswirtschaftlichen Indikatoren für die modellbasierte Prognose aller Wahrscheinlichkeit nach kaum einen Mehrwert liefern.

Da das Rauschen in den Zeitreihen zum täglichen Kupferpreis und zu den täglichen Kupferreserven sehr groß ist und das Rauschen in den Zeitreihen die saisonale Komponente, als auch die Trendkomponente, augenscheinlich dominiert, soll im Folgenden noch überprüft werden, ob eine wöchentliche oder monatliche Prognose (Aggregation der Daten) hilfreich sein kann, um signifikantere Muster in der Zeitreihe zu identifizieren. Hierfür soll explizit noch einmal auf die Themen der Saisonalität, den Trend, das Rauschen und die Autokorrelation auf einem etwas stärker aggregierteren Datensatz geschaut werden.

Aggregation der Daten (Woche)

Vorbereitung der Daten

In [67]:
df_copper_economic1 = df_copper_economic.set_index('date')
In [68]:
df_copper_economic_week = df_copper_economic1.resample('W').mean()
In [69]:
df_copper_economic_week.head()
Out[69]:
lme_copper_cash lme_copper_three_month lme_copper_stock year CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen CL_Produktionsmenge in 1000 Tonnen ... MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen quarter month weekofyear weekday Global_Produktionsmenge in 1000 Tonnen Global_Verbrauch in 1000 Tonnen
date
2012-01-08 7574.75 7592.75 369312.5 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1.0 1.0 1.0 2.5 16383.0 14429.0
2012-01-15 7749.00 7760.30 362320.0 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1.0 1.0 2.0 2.0 16383.0 14429.0
2012-01-22 8188.60 8205.10 352090.0 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1.0 1.0 3.0 2.0 16383.0 14429.0
2012-01-29 8408.20 8423.80 340215.0 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1.0 1.0 4.0 2.0 16383.0 14429.0
2012-02-05 8379.00 8399.90 329605.0 2012.0 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 38.0 76.0 30.0 20.0 1.0 1.6 5.0 2.0 16383.0 14429.0

5 rows × 35 columns

Autokorrelation und Decomposition-Plots

Autokorrelation und partielle Autokorrelation

In [70]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferpreisentwicklung
fig = tsaplots.plot_acf(df_copper_economic_week["lme_copper_cash"], lags=100)
plt.title('Autokorrelation (ACF) des Kupferpreises')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper price)")
plt.show()
In [71]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferbestandsentwicklung
fig = tsaplots.plot_acf(df_copper_economic_week["lme_copper_stock"], lags=100)
plt.title('Autokorrelation (ACF) der Kupferreserven')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper stock)")
plt.show()
In [72]:
# Plotten der autoregressiven Komponente (Autokorrelation) innerhalb der Kupferpreisentwicklung
fig = tsaplots.plot_pacf(df_copper_economic_week["lme_copper_cash"], lags=50)
plt.title('Partielle Autokorrelation des Kupferpreises')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper price)")
plt.show()
C:\Users\woelk\anaconda3\envs\condatascience2\lib\site-packages\statsmodels\graphics\tsaplots.py:348: FutureWarning: The default method 'yw' can produce PACF values outside of the [-1,1] interval. After 0.13, the default will change tounadjusted Yule-Walker ('ywm'). You can use this method now by setting method='ywm'.
  warnings.warn(
In [73]:
# Plotten der partiellen Autokorrelation innerhalb der Kupferbestandsentwicklung
fig = tsaplots.plot_pacf(df_copper_economic_week["lme_copper_stock"], lags=100)
plt.title('Partielle Autokorrelation der Kupferreserven')
plt.xlabel("Lag")
plt.ylabel("Correlation coefficient (copper stock)")
plt.show()
C:\Users\woelk\anaconda3\envs\condatascience2\lib\site-packages\statsmodels\graphics\tsaplots.py:348: FutureWarning: The default method 'yw' can produce PACF values outside of the [-1,1] interval. After 0.13, the default will change tounadjusted Yule-Walker ('ywm'). You can use this method now by setting method='ywm'.
  warnings.warn(

Decomposition-Plots (Saisonalität, Trend, Rauschen)

In [74]:
# Plotten der saisonalen Muster der Zeitreihe (Kupferpreis)
decomposition_week = sm.tsa.seasonal_decompose(df_copper_economic_week["lme_copper_cash"], period = 53)
decomposition_week.seasonal.plot()
plt.title('Saisonalität des Kupferpreises')
plt.show()
In [75]:
# Plotten der saisonalen Muster der Zeitreihe (Kupferreserven)
decomposition2_week = sm.tsa.seasonal_decompose(df_copper_economic_week["lme_copper_stock"], period = 53)
decomposition2_week.seasonal.plot()
plt.title('Saisonalität des Kupferpreises')
plt.show()
In [76]:
# Plotten des Trendverlaufs des Kupferpreises in der gegebenen Zeitreihe von 2012-2020

decomposition_week.trend.plot()
plt.ylabel('copper_price')
plt.title('Trendverlauf des Kupferpreises')
plt.show()
In [77]:
# Plotten des Trendverlaufs des Kupferreserven in der gegebenen Zeitreihe von 2012-2020

decomposition2_week.trend.plot()
plt.ylabel('copper_stock')
plt.title('Trendverlauf des Kupferpreises')
plt.show()
In [78]:
# Plotten des Rauschens in der Zeitreihe des Kupferpreises in der gegebenen Zeitreihe von 2012-2020

decomposition_week.resid.plot()
plt.ylabel('copper_price')
plt.title('Trendverlauf des Kupferpreises')
plt.show()
In [79]:
# Plotten des Rauschens in der Zeitreihe der Kupferreserven in der gegebenen Zeitreihe von 2012-2020

decomposition2_week.resid.plot()
plt.ylabel('copper_stock')
plt.title('Trendverlauf des Kupferpreises')
plt.show()

Erkenntnis: Auch auf wöchentlicher Basis lassen sich bei genauerer Betrachtung der saisonalen Muster, des Trendverlaufs und des Rauschens der Zeitreihen zum Kupferpreis und zu den Kupferreserven keine neuen Erkenntnisse gewinnen.

Die saisonalen Strukturen, genau wie die Trendkomponente und das Rauschen in der Zeitreihe, zeichnet sich auf wöchentlicher Basis ähnlich ab, wie bei der tagesbasierten Betrachtung der Zeitreihen.

Die Verzögerung der Zeitreihe scheint über das Lag von 2 hinaus ebenfalls keinen größeren Mehrwert zu liefern. Die Autokorrelation beim Kupferpreis ist zwar bis zu einem Lag von ca. 30 noch positiv und statistisch signifikant, im Rahmen der partiellen Autokorrelation wird aber ersichtlich, dass ein Lag von > 2 wenig statistischen Mehrwert im Vergleich zu den vorangegangenen Lags liefert.

Im Rahmen der Autokorrelation werden allerdings die saisonalen Strukturen der beiden Zeitreihen noch einmal sichtbar. Das Rauschen (als zufällige Komponente der statistischen Kupferpreisentwicklung) wird bei der Betrachtung der Zeitreihen, insbesondere beim Kupferpreis, etwas geglättet, was für die spätere Modellierung und Prognose der wöchentlichen durchschnittlichen Kupferpreise eventuell hilfreich sein kann.

Speichern des Datensatzes für die Data Preparation und das Data Preprocessing

In [94]:
df_copper_economic_basis = df_copper_economic.drop(['year','quarter','month','weekofyear','weekday'], axis = 1)
In [95]:
df_copper_economic_basis.head()
Out[95]:
date lme_copper_cash lme_copper_three_month lme_copper_stock CN_BIP pro Kopf in USD US_BIP pro Kopf in USD Global_Nachfrage in Mio. Tonnen EU_Produktionsmenge in 1000 Tonnen AU_Produktionsmenge in 1000 Tonnen CL_Produktionsmenge in 1000 Tonnen ... CL_Reserven in Mio. Tonnen CN_Reserven in Mio. Tonnen US_Reserven in Mio. Tonnen CG_Reserven in Mio. Tonnen MX_Reserven in Mio. Tonnen PE_Reserven in Mio. Tonnen RU_Reserven in Mio. Tonnen ZM_Reserven in Mio. Tonnen Global_Produktionsmenge in 1000 Tonnen Global_Verbrauch in 1000 Tonnen
251 2012-01-03 7661.0 7680.0 371575 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0 16383.0 14429.0
250 2012-01-04 7652.0 7665.5 369150 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0 16383.0 14429.0
249 2012-01-05 7471.0 7485.5 368400 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0 16383.0 14429.0
248 2012-01-06 7515.0 7540.0 368125 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0 16383.0 14429.0
247 2012-01-09 7503.0 7508.0 366900 6282.71 51736.74 20.48 3882.0 958.0 5430.0 ... 190.0 30.0 39.0 20.0 38.0 76.0 30.0 20.0 16383.0 14429.0

5 rows × 31 columns

In [96]:
df_copper_economic_basis_week = df_copper_economic_week.drop(['year','quarter','month','weekofyear','weekday'], axis = 1)
In [97]:
df_copper_economic_basis_week.to_csv("C:\\Users\\woelk\\OneDrive\\Dokumente\\Studium - HdM Stuttgart\\Machine Learning\\0 - Projekt\\Kupferpreisprognose\\copper_economic_enriched_week.csv", sep=",", encoding = 'utf-8')